use crate::{
    parser::Value,
    runtime::{Env, FuncBinds},
};

use super::Builtin;

pub fn bind(env: &mut FuncBinds) {
    env.bind_builtin("+", Add);
    env.bind_builtin("%", Mod);
}

struct Add;

impl Builtin for Add {
    fn call(&self, _: &Env, argv: &[Value]) -> Result<Value, ()> {
        let mut x = 0;
        for each in argv {
            x += each.as_integer()?;
        }
        Ok(Value::Integer(x))
    }
}

struct Mod;

impl Builtin for Mod {
    fn call(&self, _: &Env, argv: &[Value]) -> Result<Value, ()> {
        let [Value::Integer(a), Value::Integer(b)] = argv else {
            return Err(());
        };

        Ok(Value::Integer(a % b))
    }
}
